#include <at89lp4052.h>
//#include <xc822.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <dsw.h>
#include <rtx51tny.h>

#include <konstanty.inc>

#define PSD
#define SIMUL

#define SYSTEM	0
#define	REG0		1
#define	REG1		2
#define	SERIAL	3

sbit LED	=	P1^0;
sbit LED0	=	P1^1;
sbit LED1	=	P1^2;

extern unsigned char Read_Eprom_AT24C32(unsigned char,unsigned int);
extern void Write_Eprom_AT24C32(unsigned char,unsigned int,unsigned char);

typedef struct _Datum
{
	unsigned char q,m;
	unsigned int Y;
}
Datum_t;

Datum_t Date;

unsigned char Gregorian(Datum_t Date)
{
	unsigned char J,K;
	J=Date.Y/100;
	K=Date.Y%100;
	switch(Date.m)
		{
			case	1	:	
			case	2	:	Date.m+=12;	K--;
			default	:	return(((((Date.q+(13*(Date.m+1)/5)+K+(K/4)+(J/4)+(5*J))%7)+5)%7)+1);	break;
		}	
}

typedef union //_time
{
 struct
 {
	unsigned char Hod:5;		
	unsigned char Min:6;		
	unsigned int	Sek:10;	//10x rychlejsie ako na AT89C4051 !!!
	unsigned char Den:5;
	unsigned char Mes:4;
	unsigned int	Rok:11;	//11 bitov - do roku 2048
	unsigned char	Day:3;	//1..7, pondelok .. nedela
	//unsigned char Rg0:1;
	//unsigned char Rg1:1;
	//unsigned char Rg2:1;
 }
 Time;
 unsigned char _Pack_Time_Struct[6];	//Vytvorenie 48 bitovej premennej
}
Time;

Time Cas = {6,15,55,28,4,1971,1};

#define Kp0	1.0
#define Ti0	2.0
#define Td0	3.0
#define dT0	0.25

#define Kp1	1.0
#define Ti1	2.0
#define Td1	3.0
#define dT1	0.25

#ifdef PSD

typedef struct
{
	int E0,E1,E2;
	unsigned char Y0,Y1;
	float KA,KB,KC;
}
PID_struct_t;

code PID_struct_t Reg0 	= {0x0001,0x0002,0x0003,0x0004,0x0005,Kp0*(1.0+dT0/(2.0*Ti0)),Kp0*(1.0-dT0/(2.0*Ti0)),Kp0*(Td0/dT0)};
code PID_struct_t Reg1	= {0x0005,0x0004,0x0003,0x0002,0x0001,Kp1*(1.0+dT1/(2.0*Ti1)),Kp1*(1.0-dT1/(2.0*Ti1)),Kp1*(Td1/dT1)};

#else

typedef struct
{
	int E0,E1;
	unsigned char Y0,Y1;
	float KA,KB;
}
PID_struct_t;

code PID_struct_t Reg0 	= {0x0001,0x0002,0x0003,0x0004,Kp0*(1.0+dT0/(2.0*Ti0),Kp0*(1.0-dT0/(2.0*Ti0)))};
code PID_struct_t Reg1	= {0x0004,0x0003,0x0002,0x0001,Kp1*(1.0+dT1/(2.0*Ti1),Kp1*(1.0-dT1/(2.0*Ti1)))};

#endif

unsigned char malloc_mempool0[sizeof(PID_struct_t)];
unsigned char malloc_mempool1[sizeof(PID_struct_t)];

void Regulator0(void) _task_ REG0
{
	PID_struct_t *ptr;
	ptr=(PID_struct_t*)&malloc_mempool0;
	//memcpy(ptr,&Reg0,sizeof(PID_struct_t));		//Init default constant regulator
	for(;;)
	{
		LED0=1;
		#ifdef PSD
		ptr->Y0=ptr->Y1+ptr->KA*ptr->E0-ptr->KB*ptr->E1+ptr->KC*ptr->E2;
		ptr->Y1=ptr->Y0;
		ptr->E2=ptr->E1;
		ptr->E1=ptr->E0;
		#else
		ptr->Y0=ptr->Y1+ptr->KA*ptr->E0-ptr->KB*ptr->E1;
		#endif
		ptr->Y1=ptr->Y0;
		ptr->E1=ptr->E0;
		//if(ptr->Y0>0x7FFF) ptr->Y0=0x7FFF;
		//if(ptr->Y0<0x8000) ptr->Y0=0x8000;
		LED0=0;
		//printf("Y00=%4x\r\n",ptr->Y0);
		os_wait(K_TMO,(unsigned char)(dT0*1000),NULL);
	}
}

void Regulator1(void) _task_ REG1
{
	PID_struct_t *ptr;
	ptr=(PID_struct_t*)&malloc_mempool1;
	//memcpy(ptr,&Reg1,sizeof(PID_struct_t));		//Init default constant regulator
	for(;;)
	{
		LED1=1;
		#ifdef PSD
		ptr->Y0=ptr->Y1+ptr->KA*ptr->E0-ptr->KB*ptr->E1+ptr->KC*ptr->E2;
		ptr->Y1=ptr->Y0;
		ptr->E2=ptr->E1;
		ptr->E1=ptr->E0;		
		#else
		ptr->Y0=ptr->Y1+ptr->KA*ptr->E0-ptr->KB*ptr->E1;
		ptr->Y1=ptr->Y0;
		ptr->E1=ptr->E0;
		#endif
		//if(ptr->Y0>0x7FFF) ptr->Y0=0x7FFF;
		//if(ptr->Y0<0x8000) ptr->Y0=0x8000;
		LED1=0;
		//printf("Y10=%4x\r\n",ptr->Y0);
		os_wait(K_TMO,(unsigned char)(dT1*1000),NULL);
	}
}

void Serial(void) _task_ SERIAL
{	
	unsigned char i;
	PID_struct_t *ptr;
	TMOD|=0x20;
	TCON|=0x20;
	SCON|=0x50;
	PCON|=0x80;									//19200 bps
	TH1=TL1=0xC4;								//Pre 18.432MHz je 0xC4 a pre 11.059MHz je 0xDC
	TR1=1;
	//TI=1;											//Len pre pripad pouzitia printf() a scanf()
	for(;;)
	{
		switch(os_wait(K_TMO+K_SIG,0xFF,NULL))
		{
			case	TMO_EVENT	:	
			case	SIG_EVENT	:	ptr=(PID_struct_t*)&malloc_mempool0;		//Nacitam prvy regulator
												for(i=0; i<sizeof(PID_struct_t); i++)
												{
													SBUF=((char*)ptr)[i];
													while(TI==0) os_switch_task();
													TI=0;
												}
												ptr=(PID_struct_t*)&malloc_mempool1;	//Nacitam druhy regulator
												for(i=0; i<sizeof(PID_struct_t); i++)
												{
													SBUF=((char*)ptr)[i];
													while(TI==0) os_switch_task();
													TI=0;
												}
												break;
		}
	}
}

sfr CLKREG	= 0x87;

void System(void) _task_ SYSTEM
{
	unsigned char i;
	PID_struct_t *ptr;
	ptr=(PID_struct_t*)&malloc_mempool0;
	//code *Asm_Date = {__DATE2__};
	//code *Asm_Time = {__TIME__};
	//sprintf(__DATE2__,"%02bd/%02bd/%02bd",Cas.Time.Mes,Cas.Time.Den,Cas.Time.Rok);
	//sprintf(__TIME__,"%02bd:%02bd:%02bd",Cas.Time.Hod,Cas.Time.Min,Cas.Time.Sek);
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)ptr)[i]=Read_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i);}
	#ifdef SIMUL
	if(memcmp(ptr,&Reg0,sizeof(PID_struct_t))!=0)
	{
		memcpy(ptr,&Reg0,sizeof(PID_struct_t));		//Init and copy default constant regulator
		for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i,((char*)ptr)[i]);}
	}
	#else
	memcmp(ptr,&Reg0,sizeof(PID_struct_t));																																								//Je to tu len kvoli chybovemu hlaseniu !!!
	Write_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1,Read_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1));		//Je to tu len kvoli chybovemu hlaseniu !!!
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)ptr)[i]=Read_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i);}
	#endif
	
	ptr=(PID_struct_t*)&malloc_mempool1;
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)ptr)[i]=Read_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i);}
	#ifdef SIMUL
	if(memcmp(ptr,&Reg1,sizeof(PID_struct_t))!=0)
	{
		memcpy(ptr,&Reg1,sizeof(PID_struct_t));		//Init and copy default constant regulator
		for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i,((char*)ptr)[i]);}
	}
	#else
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)ptr)[i]=Read_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i);}
	#endif
	CLKREG=0x51;															//Compatibility mode AT89S52
	TCONB=0x24;	
	Date.q=Cas.Time.Den;
	Date.m=Cas.Time.Mes;
	Date.Y=Cas.Time.Rok;
	Cas.Time.Day=Gregorian(Date);
	os_create_task(REG0);
	os_create_task(REG1);
	os_create_task(SERIAL);
	//Write_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1,Read_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1));
	for(;;)
	{
		LED=~LED;
		os_wait(K_IVL,100,NULL);
		if(++Cas.Time.Sek==600)
		{
			Cas.Time.Sek=0;
			os_send_signal(SERIAL);
			if(++Cas.Time.Min==60)
			{
				Cas.Time.Min=0;
				if(++Cas.Time.Hod==24)
				{
					Cas.Time.Hod=0;
				}
			}
		}
	}
}









//




#include <at89lp4052.h>
//#include <xc822.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <dsw.h>
#include <rtx51tny.h>

#include <konstanty.inc>

#define PSDx
#define SIMUL

#define SYSTEM	0
#define	REG0		1
#define	REG1		2
#define	SERIAL	3

sbit LED	=	P1^0;
sbit LED0	=	P1^1;
sbit LED1	=	P1^2;

extern unsigned char Read_Eprom_AT24C32(unsigned char,unsigned int);
extern void Write_Eprom_AT24C32(unsigned char,unsigned int,unsigned char);

typedef struct _Datum
{
	unsigned char q,m;
	unsigned int Y;
}
Datum_t;

Datum_t Date;

unsigned char Gregorian(Datum_t Date)
{
	unsigned char J,K;
	J=Date.Y/100;
	K=Date.Y%100;
	switch(Date.m)
		{
			case	1	:	
			case	2	:	Date.m+=12;	K--;
			default	:	return(((((Date.q+(13*(Date.m+1)/5)+K+(K/4)+(J/4)+(5*J))%7)+5)%7)+1);	break;
		}	
}

typedef union //_time
{
 struct
 {
	unsigned char Hod:5;		
	unsigned char Min:6;		
	unsigned int	Sek:10;	//10x rychlejsie ako na AT89C4051 !!!
	unsigned char Den:5;
	unsigned char Mes:4;
	unsigned int	Rok:11;	//11 bitov - do roku 2048
	unsigned char	Day:3;	//1..7, pondelok .. nedela
	//unsigned char Rg0:1;
	//unsigned char Rg1:1;
	//unsigned char Rg2:1;
 }
 Time;
 unsigned char _Pack_Time_Struct[6];	//Vytvorenie 48 bitovej premennej
}
Time;

Time Cas = {6,15,55,28,4,1971,1};

#define Kp0	1.0
#define Ti0	2.0
#define Td0	3.0
#define dT0	0.25

#define Kp1	1.0
#define Ti1	2.0
#define Td1	3.0
#define dT1	0.25

#ifdef PSD

typedef struct
{
	int E0,E1,E2;
	unsigned char Y0,Y1;
	float KA,KB,KC;
}
PID_struct_t;

PID_struct_t Reg0 = {0x0001,0x0002,0x0003,0x0004,0x0005,Kp0*(1.0+dT0/(2.0*Ti0)),Kp0*(1.0-dT0/(2.0*Ti0)),Kp0*(Td0/dT0)};
PID_struct_t Reg1	= {0x0005,0x0004,0x0003,0x0002,0x0001,Kp1*(1.0+dT1/(2.0*Ti1)),Kp1*(1.0-dT1/(2.0*Ti1)),Kp1*(Td1/dT1)};

#else

typedef struct
{
	int E0,E1;
	unsigned char Y0,Y1;
	float KA,KB;
}
PID_struct_t;

PID_struct_t Reg0 = {0x0001,0x0002,0x0003,0x0004,Kp0*(1.0+dT0/(2.0*Ti0),Kp0*(1.0-dT0/(2.0*Ti0)))};
PID_struct_t Reg1	= {0x0004,0x0003,0x0002,0x0001,Kp1*(1.0+dT1/(2.0*Ti1),Kp1*(1.0-dT1/(2.0*Ti1)))};

#endif

void Regulator0(void) _task_ REG0
{
	for(;;)
	{
		LED0=1;
		#ifdef PSD
		Reg0.Y0=Reg0.Y1+Reg0.KA*Reg0.E0-Reg0.KB*Reg0.E1+Reg0.KC*Reg0.E2;
		Reg0.Y1=Reg0.Y0;
		Reg0.E2=Reg0.E1;
		Reg0.E1=Reg0.E0;
		#else
		Reg0.Y0=Reg0.Y1+Reg0.KA*Reg0.E0-Reg0.KB*Reg0.E1;
		#endif
		Reg0.Y1=Reg0.Y0;
		Reg0.E1=Reg0.E0;
		//if(Reg0.Y0>=0x7FFF) Reg0.Y0=0x7FFF;
		//if(Reg0.Y0<=0x8000) Reg0.Y0=0x8000;
		LED0=0;
		//printf("Y00=%4x\r\n",Reg0.Y0);
		os_wait(K_TMO,(unsigned char)(dT0*1000),NULL);
	}
}

void Regulator1(void) _task_ REG1
{
	for(;;)
	{
		LED1=1;
		#ifdef PSD
		Reg1.Y0=Reg1.Y1+Reg1.KA*Reg1.E0-Reg1.KB*Reg1.E1+Reg1.KC*Reg1.E2;
		Reg1.Y1=Reg1.Y0;
		Reg1.E2=Reg1.E1;
		Reg1.E1=Reg1.E0;		
		#else
		Reg1.Y0=Reg1.Y1+Reg1.KA*Reg1.E0-Reg1.KB*Reg1.E1;
		Reg1.Y1=Reg1.Y0;
		Reg1.E1=Reg1.E0;
		#endif
		//if(Reg0.Y0>=0x7FFF) Reg0.Y0=0x7FFF;
		//if(Reg0.Y0<=0x8000) Reg0.Y0=0x8000;
		LED1=0;
		//printf("Y10=%4x\r\n",Reg1.Y0);
		os_wait(K_TMO,(unsigned char)(dT1*1000),NULL);
	}
}

void Serial(void) _task_ SERIAL
{	
	unsigned char i;
	TMOD|=0x20;
	TCON|=0x20;
	SCON|=0x50;
	PCON|=0x80;									//19200 bps
	TH1=TL1=0xC4;								//Pre 18.432MHz je 0xC4 a pre 11.059MHz je 0xDC
	TR1=1;
	//TI=1;											//Len pre pripad pouzitia printf() a scanf()
	for(;;)
	{
		switch(os_wait(K_TMO+K_SIG,0xFF,NULL))
		{
			case	TMO_EVENT	:	
			case	SIG_EVENT	:	for(i=0; i<sizeof(PID_struct_t); i++)	//Nacitam prvy regulator
												{
													SBUF=((char*)&Reg0)[i];
													while(TI==0) os_switch_task();
													TI=0;
												}
												for(i=0; i<sizeof(PID_struct_t); i++)	//Nacitam druhy regulator
												{
													SBUF=((char*)&Reg1)[i];
													while(TI==0) os_switch_task();
													TI=0;
												}
												break;
		}
	}
}

sfr CLKREG	= 0x87;

void System(void) _task_ SYSTEM
{
	unsigned char i;
	//code *Asm_Date = {__DATE2__};
	//code *Asm_Time = {__TIME__};
	//sprintf(__DATE2__,"%02bd/%02bd/%02bd",Cas.Time.Mes,Cas.Time.Den,Cas.Time.Rok);
	//sprintf(__TIME__,"%02bd:%02bd:%02bd",Cas.Time.Hod,Cas.Time.Min,Cas.Time.Sek);
	
	#ifdef SIMUL
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i,((char*)&Reg0)[i]);}
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg0)[i]=Read_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i);}
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i,((char*)&Reg1)[i]);}
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg1)[i]=Read_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i);}
	#else
	//Write_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1,Read_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1));		//Je to tu len kvoli chybovemu hlaseniu !!!
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i,((char*)&Reg0)[i]);}
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg0)[i]=Read_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i);}
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i,((char*)&Reg1)[i]);}
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg1)[i]=Read_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i);}
	#endif
	
	/*
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg0)[i]=Read_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i);}
	#ifdef SIMUL
	if(memcmp(&Reg0,&Reg0,sizeof(PID_struct_t))!=0)
	{
		memcpy(&Reg0,&Reg0,sizeof(PID_struct_t));		//Init and copy default constant regulator
		for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i,((char*)&Reg0)[i]);}
	}
	#else
	memcmp(&Reg0,&Reg0,sizeof(PID_struct_t));																																								//Je to tu len kvoli chybovemu hlaseniu !!!
	Write_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1,Read_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1));		//Je to tu len kvoli chybovemu hlaseniu !!!
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg0)[i]=Read_Eprom_AT24C32(AddrAT24c32,0*sizeof(PID_struct_t)+i);}
	#endif
	
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg0)[i]=Read_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i);}
	#ifdef SIMUL
	if(memcmp(&Reg1,&Reg1,sizeof(PID_struct_t))!=0)
	{
		memcpy(&Reg1,&Reg1,sizeof(PID_struct_t));		//Init and copy default constant regulator
		for(i=0x0000; i<sizeof(PID_struct_t); i++) {Write_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i,((char*)&Reg1)[i]);}
	}
	#else
	for(i=0x0000; i<sizeof(PID_struct_t); i++) {((char*)&Reg1)[i]=Read_Eprom_AT24C32(AddrAT24c32,1*sizeof(PID_struct_t)+i);}
	#endif
	*/
	
	CLKREG=0x51;															//Compatibility mode AT89S52
	TCONB=0x24;	
	Date.q=Cas.Time.Den;
	Date.m=Cas.Time.Mes;
	Date.Y=Cas.Time.Rok;
	Cas.Time.Day=Gregorian(Date);
	os_create_task(REG0);
	os_create_task(REG1);
	//os_create_task(SERIAL);
	//Write_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1,Read_Eprom_AT24C32(AddrAT24c32,2*sizeof(PID_struct_t)+1));
	for(;;)
	{
		LED=~LED;
		os_wait(K_IVL,100,NULL);
		if(++Cas.Time.Sek==600)
		{
			Cas.Time.Sek=0;
			os_send_signal(SERIAL);
			if(++Cas.Time.Min==60)
			{
				Cas.Time.Min=0;
				if(++Cas.Time.Hod==24)
				{
					Cas.Time.Hod=0;
				}
			}
		}
	}
}







#include <reg51.h>

#define Dlzka	6

sbit	SDA = P1^7;
sbit	SCL = P1^6;

extern void Delay(unsigned char);

void I2C_Start(void)
{
 SCL=SDA=1;			//AGSI drivers vyzaduje !!!, Zacalo davat dobre vysledky s AGSI drivers
 Delay(Dlzka);	//AGSI drivers vyzaduje !!!, Zacalo davat dobre vysledky s AGSI drivers
 SDA=0;
 Delay(Dlzka);
 SCL=0;
 Delay(Dlzka);
}

void I2C_Bit(unsigned char Data)
{
 SDA=Data;
 Delay(Dlzka);
 SCL=1;
 Delay(Dlzka);
 SCL=0;
 Delay(Dlzka);
}

unsigned char I2C_ReadBit(void)
{
 register unsigned char Result;
 #ifndef SIMUL
  SDA=1;				//Zacalo davat dobre vysledky s 80C552 na BAST552....
 #endif
 Delay(Dlzka);
 SCL=1;
 Delay(Dlzka);
 Result=SDA;
 Delay(Dlzka);
 SCL=0;
 Delay(Dlzka);
 return(Result);
}

void I2C_Stop(void)
{
 SDA=0;
 Delay(Dlzka);
 SCL=1;
 Delay(Dlzka);
 SDA=1;
 Delay(Dlzka);
}

unsigned char I2C_Read(unsigned char doACK)
{
 register unsigned char i, Result=0;
 for(i=0x00; i<0x08; i++)
  {
   Result<<=1;
   Result|=(I2C_ReadBit()&0x01);
  }
 if(doACK==0) I2C_Bit(1);  /* No ACK */ else I2C_Bit(0);  /* Do the ACK */
 return(Result);
}

unsigned char I2C_SendByte(unsigned char Data)
{
 register unsigned char i;
 for(i=0x00; i<0x08; i++)
  {
   if(Data&0x80) I2C_Bit(1); else I2C_Bit(0);
   Data<<=1;
  }
 return(I2C_ReadBit());	
}

unsigned char I2C_SendAddr(unsigned char Addr)
{
 I2C_Start();
 return(I2C_SendByte(Addr));
}

#ifdef BLOCK

unsigned char i2c_writeblock(unsigned char Addr, unsigned char *barr,int length)
{
  register int i;
  if(I2C_SendAddr(Addr&0xFE)!=0) return(1);
  for(i=0x00;i<length;i++) if(I2C_SendByte(barr[i])!=0) return(1);
  I2C_Stop();
  return(0);
}

/*
 * \brief         Perform I2C start, Addr selection, read specified
 *                number of bytes and I2C stop.
 *
 * \param Addr Address of device to select.  Upper 7 bits
 *                are Addr, LSbit automatically set to 1 by
 *                function.
 * \param barr    Array destination for read bytes
 * \param offset  Offset location for first read
 * \param length  Number of bytes to read
 *
 * \return        0 if device acknowledged Addr selection and data transfer
 */
//---------------------------------------------------------------------------

unsigned char i2c_readblock(unsigned char Addr, unsigned char *barr,int length)
{
  register int i;
  if(I2C_SendAddr(Addr|0x01)!=0) return(1);
  // Reduce the length by one.  The last byte must not be ACKed.
  length--;
  // Read every byte but the last
  for(i=0x00; i<length;i++) barr[i]=I2C_Read(1);
  // Don't ack the last byte
  barr[i]=I2C_Read(0);
  I2C_Stop();
  return(0);
}

/**
 * \brief         Perform I2C start, Addr selection, write specified
 *                bytes, I2C start, Addr slection, read bytes and I2C stop.
 *
 * \param Addr Address of device to select.  Upper 7 bits
 *                are Addr, LSbit automatically set to 0 by
 *                function.
 * \param barr1   Array of bytes to write
 * \param offset1 Offset to first byte to write
 * \param length1 Number of bytes to write
 * \param barr2   Array destination for read bytes
 * \param offset2 Offset location for first read
 * \param length2 Number of bytes to read
 *
 * \return        0 if device acknowledged Addr selection and data transfer
 */
//---------------------------------------------------------------------------

unsigned char i2c_writereadblock(unsigned char Addr, unsigned char *barr1,int length1, unsigned char *barr2,int length2)
{
  register int i;
  if(I2C_SendAddr(Addr&0xFE)!=0) return (1);
  for(i=0x00; i<length1;i++) I2C_SendByte(barr1[i]);
  SDA=1;
  Delay(Dlzka);
  SCL=1;
  Delay(Dlzka);
  if(I2C_SendAddr(Addr|0x01)!=0) return(1);
  // Reduce the length by one.  The last byte must not be ACKed.
  length2--;
  // Read every byte but the last
  for(i=0x00;i<length2;i++) barr2[i]=I2C_Read(1);
  // Don't ack the last byte
  barr2[i]=I2C_Read(0);
  I2C_Stop();
  return(0);
}

#endif






#include <reg552.h>

//sbit SDA = P1^7;
//sbit SCL = P1^6;

#define	Time	2

extern void Delay(unsigned char);

//#define I2C_ENABLE_SCL_WAIT_FOR_SLOW_SLAVES 0
#define I2C_MAXIMUM_SCL_WAITCOUNT 10000				//10000
#define I2C_DELAY_LOOP_COUNT 2
/*
void Delay(void)
{
  int loop;
  for (loop=0; loop<I2C_DELAY_LOOP_COUNT; loop++);	//S touto rutinou to fungovalo a ako to pojde s tou assemblerovskou, neviem ...
}
*/
#ifdef I2C_ENABLE_SCL_WAIT_FOR_SLOW_SLAVES

void I2C_WaitforSCL(void)
{
  int waitcount;
  for (waitcount=0x0000; waitcount<I2C_MAXIMUM_SCL_WAITCOUNT; waitcount++)
  {
   if(SCL==1) return;
  }
}

#endif

void I2C_Start(void)
{
 SCL=SDA=1;			//AGSI drivers vyzaduje !!!, Zacalo davat dobre vysledky s AGSI drivers
 Delay(Time);		//AGSI drivers vyzaduje !!!, Zacalo davat dobre vysledky s AGSI drivers
 SDA=0;
 Delay(Time);
 SCL=0;
 Delay(Time);
}

void I2C_Bit(unsigned char Data)
{
 SDA=Data;
 Delay(Time);
 SCL=1;
 #ifdef I2C_ENABLE_SCL_WAIT_FOR_SLOW_SLAVES
 I2C_WaitforSCL();
 #endif 
 Delay(Time);
 SCL=0;
 Delay(Time);
}

unsigned char I2C_ReadBit(void)
{
 unsigned char Result;
 #ifndef SIMUL
 SDA=1;				//Zacalo davat dobre vysledky s 80C552 na BAST552....
 #endif
 Delay(Time);
 SCL=1;
 #ifdef I2C_ENABLE_SCL_WAIT_FOR_SLOW_SLAVES
 I2C_WaitforSCL();
 #endif 
 Delay(Time);
 Result=SDA;
 Delay(Time);
 SCL=0;
 Delay(Time);
 return(Result);
}

void I2C_Stop(void)
{
 SDA=0;
 Delay(Time);
 SCL=1;
 Delay(Time);
 SDA=1;
 Delay(Time);
}

unsigned char I2C_Read(unsigned char doACK)
{
 unsigned char i, Result=0;
 for(i=0x00; i<0x08; i++)
  {
   Result<<=1;
   //Result|=(I2C_ReadBit()&0x01);	//Nie je to tu zbytocne ???
	 Result|=(I2C_ReadBit());
  }
 if(doACK==0) I2C_Bit(1);  /* No ACK */ else I2C_Bit(0);  /* Do float ACK */
 return(Result);
}

unsigned char I2C_SendByte(unsigned char Data)
{
 unsigned char i;
 for(i=0x00; i<0x08; i++)
  {
   if(Data&0x80) I2C_Bit(1); else I2C_Bit(0);
   Data<<=1;
  }
 return(I2C_ReadBit());	
}

unsigned char I2C_SendAddr(unsigned char Addr)
{
 I2C_Start();
 return(I2C_SendByte(Addr));
}

#ifdef BLOCK

unsigned char i2c_writeblock(unsigned char Addr, unsigned char *barr,int length)
{
  int i;
  if(I2C_SendAddr(Addr&0xFE)!=0) return(1);
  for(i=0x00;i<length;i++) if(I2C_SendByte(barr[i])!=0) return(1);
  I2C_Stop();
  return(0);
}

/*
 * \brief         Perform I2C start, Addr selection, read specified
 *                number of bytes and I2C stop.
 *
 * \param Addr Address of device to select.  Upper 7 bits
 *                are Addr, LSbit automatically set to 1 by
 *                function.
 * \param barr    Array destination for read bytes
 * \param offset  Offset location for first read
 * \param length  Number of bytes to read
 *
 * \return        0 if device acknowledged Addr selection and data transfer
 */
//---------------------------------------------------------------------------

unsigned char i2c_readblock(unsigned char Addr, unsigned char *barr,int length)
{
  int i;
  if(I2C_SendAddr(Addr|0x01)!=0) return(1);
  // Reduce float length by one.  The last byte must not be ACKed.
  length--;
  // Read every byte but float last
  for(i=0x00; i<length;i++) barr[i]=I2C_Read(1);
  // Don't ack float last byte
  barr[i]=I2C_Read(0);
  I2C_Stop();
  return(0);
}

/**
 * \brief         Perform I2C start, Addr selection, write specified
 *                bytes, I2C start, Addr slection, read bytes and I2C stop.
 *
 * \param Addr Address of device to select.  Upper 7 bits
 *                are Addr, LSbit automatically set to 0 by
 *                function.
 * \param barr1   Array of bytes to write
 * \param offset1 Offset to first byte to write
 * \param length1 Number of bytes to write
 * \param barr2   Array destination for read bytes
 * \param offset2 Offset location for first read
 * \param length2 Number of bytes to read
 *
 * \return        0 if device acknowledged Addr selection and data transfer
 */
//---------------------------------------------------------------------------

unsigned char i2c_writereadblock(unsigned char Addr, unsigned char *barr1,int length1, unsigned char *barr2,int length2)
{
  int i;
  if(I2C_SendAddr(Addr&0xFE)!=0) return (1);
  for(i=0x00; i<length1;i++) I2C_SendByte(barr1[i]);
  SDA=1;
  Delay(Time);
  SCL=1;
  Delay(Time);
  if(I2C_SendAddr(Addr|0x01)!=0) return(1);
  // Reduce float length by one.  The last byte must not be ACKed.
  length2--;
  // Read every byte but float last
  for(i=0x00;i<length2;i++) barr2[i]=I2C_Read(1);
  // Don't ack float last byte
  barr2[i]=I2C_Read(0);
  I2C_Stop();
  return(0);
}

#endif